package com.xjh.him.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xjh.him.common.LoginUser;
import com.xjh.him.constant.Constant;
import com.xjh.him.dao.UserGroupMapper;
import com.xjh.him.dao.UserGroupMemberMapper;
import com.xjh.him.dao.UserGroupMsgMapper;
import com.xjh.him.dao.UserMapper;
import com.xjh.him.domain.UserDO;
import com.xjh.him.domain.UserGroupDO;
import com.xjh.him.domain.UserGroupMemberDO;
import com.xjh.him.domain.UserGroupMsgDO;
import com.xjh.him.dto.usergroup.UserGroupAddDTO;
import com.xjh.him.dto.usergroup.UserGroupDTO;
import com.xjh.him.netty.NettyCore;
import com.xjh.him.netty.codec.Command;
import com.xjh.him.netty.codec.Packet;
import com.xjh.him.netty.dto.UserSessionAddNotifyDTO;
import io.netty.channel.Channel;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.xjh.tool.Checks;
import org.xjh.tool.common.ErrorMsg;
import org.xjh.tool.dto.ResultDTO;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class UserGroupServiceImpl implements IUserGroupService {

    @Autowired
    private UserGroupMemberMapper userGroupMemberMapper;

    @Autowired
    private UserGroupMsgMapper userGroupMsgMapper;

    @Autowired
    private UserGroupMapper userGroupMapper;

    @Autowired
    private UserMapper userMapper;


    @Override
    public ResultDTO<List<UserGroupDTO>> listGroup() {
        UserDO loginUser = LoginUser.getLoginUser();
        if (loginUser == null) {
            return ResultDTO.getFailureResult(ErrorMsg.ERR_SYSTEM_BUSY);
        }
        QueryWrapper<UserGroupMemberDO> queryMemberListWrapper = new QueryWrapper<>();
        queryMemberListWrapper.eq("user_id", loginUser.getId());
        queryMemberListWrapper.last("LIMIT " + Constant.DEFAULT_LIST_GROUP_SIZE);
        List<UserGroupMemberDO> memberDOList = userGroupMemberMapper.selectList(queryMemberListWrapper);
        if (Checks.isEmpty(memberDOList)) {
            return ResultDTO.getSuccessResult(new ArrayList<>());
        }

        List<Long> groupIdList = memberDOList.stream().map(UserGroupMemberDO::getUserGroupId).collect(Collectors.toList());
        List<UserGroupDO> groupDOList = userGroupMapper.selectBatchIds(groupIdList);
        List<UserGroupDTO> dtoList = new ArrayList<>();
        for (UserGroupDO groupDO : groupDOList) {
            UserGroupDTO dto = new UserGroupDTO();
            dtoList.add(dto);
            BeanUtils.copyProperties(groupDO, dto);

            QueryWrapper<UserGroupMsgDO> queryMsgWrapper = new QueryWrapper<>();
            queryMsgWrapper.eq("user_group_id", groupDO.getId());
            queryMsgWrapper.orderByDesc("id");
            queryMsgWrapper.last("LIMIT 1");
            UserGroupMsgDO groupMsgDO = userGroupMsgMapper.selectOne(queryMsgWrapper);
            if (groupMsgDO == null) {
                dto.setNewestMsg("");
                continue;
            }
            if (UserGroupMsgDO.MSG_TYPE_TEXT.equals(groupMsgDO.getMsgType())) {
                dto.setNewestMsg(groupMsgDO.getMsgContent());
            }else if (UserGroupMsgDO.MSG_TYPE_IMAGE.equals(groupMsgDO.getMsgType())) {
                dto.setNewestMsg("[图片]");
            }
            if (!groupMsgDO.getUserId().equals(loginUser.getId())) {
                UserDO userDO = userMapper.selectById(groupMsgDO.getUserId());
                dto.setNewestMsg(userDO.getNickname() + "：" + dto.getNewestMsg());
            }
        }
        return ResultDTO.getSuccessResult(dtoList);
    }

    @Transactional
    @Override
    public ResultDTO<Boolean> addGroup(UserGroupAddDTO addDTO) {
        if (Checks.isAnyEmpty(addDTO, addDTO.getUserIdList())) {
            return ResultDTO.getFailureResult(ErrorMsg.ERR_PARAMETER_IS_NULL);
        }
        if (addDTO.getUserIdList().size() == 0) {
            return ResultDTO.getFailureResult("成员不能为空");
        }
        UserDO loginUser = LoginUser.getLoginUser();
        addDTO.getUserIdList().add(0, loginUser.getId());
        List<UserDO> userDOList = userMapper.selectBatchIds(addDTO.getUserIdList());

        //创建群组
        UserGroupDO groupDO = new UserGroupDO();
        groupDO.setOwnerId(loginUser.getId());
        String[] nicknameArr = userDOList.stream().map(UserDO::getNickname).toArray(String[]::new);
        String groupName = String.join(",", nicknameArr);
        if (groupName.length() > 20) {
            groupName = groupName.substring(0, 20);
        }
        groupDO.setGroupName(groupName);
        int addGroup = userGroupMapper.insert(groupDO);
        if (addGroup == 0) {
            throw new RuntimeException("addGroup failed");
        }

        //创建群成员
        List<UserGroupMemberDO> memberDOList = new ArrayList<>();
        for (UserDO userDO : userDOList) {
            UserGroupMemberDO memberDO = new UserGroupMemberDO();
            memberDO.setUserGroupId(groupDO.getId());
            memberDO.setUserId(userDO.getId());
            memberDO.setUserNickname(userDO.getNickname());
            memberDO.setUserAvatar(userDO.getAvatarUrl());
            memberDOList.add(memberDO);
        }
        int insertMemberList = userGroupMemberMapper.insertBatch(memberDOList);
        if (insertMemberList == 0) {
            throw new RuntimeException("insertMemberList failed");
        }

        //通知群成员添加会话
        UserSessionAddNotifyDTO notifyDTO = new UserSessionAddNotifyDTO();
        notifyDTO.setTargetId(groupDO.getId());
        notifyDTO.setGroupType(UserSessionAddNotifyDTO.GROUP_TYPE_MULTIPLE);
        notifyDTO.setGroupName(groupDO.getGroupName());
        notifyDTO.setGroupAvatar(groupDO.getGroupAvatar());
        notifyDTO.setNewestMsg("");
        notifyDTO.setIsTop(false);
        for (Long userId : addDTO.getUserIdList()) {
            Channel channel = NettyCore.ACTIVE_USER_CHANNEL.get(userId);
            if (channel != null) {
                channel.writeAndFlush(Packet.create(Command.USER_SESSION_ADD_NOTIFY, notifyDTO));
            }
        }
        return ResultDTO.getSuccessResult(true);
    }
}
